from typing import Any

from aiogram import Bot, F, types
from aiogram_dialog import Dialog, DialogManager, Window
from aiogram_dialog.widgets.input import TextInput
from aiogram_dialog.widgets.kbd import (
    Back,
    Button,
    Cancel,
    Group,
    ScrollingGroup,
    Select,
    Start,
)
from aiogram_dialog.widgets.text import Format
from apscheduler.schedulers.asyncio import AsyncIOScheduler

from app.bot.dialog.dialog_states import ChangeAuthorizationSG, CreateIPSG
from app.bot.dialog.getters.servers import server_type_getter
from app.bot.dialog.getters.users import user_ips_getter
from app.bot.dialog.widgets import LocaleText
from app.bot.services.locale import Locale
from app.bot.services.loggers import logger
from app.bot.services.scheduler import jobs
from app.config import Settings
from app.database.services.allowed_ips import add_allowed_ip


async def select_ip_address(
    message: types.Message, widget: Any, manager: DialogManager
):
    manager.dialog_data["authorization_type"] = widget.widget_id
    await manager.switch_to(ChangeAuthorizationSG.select_ip_address)


async def add_ip_address(
    message: types.Message, widget: Any, manager: DialogManager, ip_address: str = None
):
    db_session = manager.middleware_data.get("db_session")
    locale: Locale = manager.middleware_data.get("locale")
    user_id = message.from_user.id
    try:
        await add_allowed_ip(db_session, user_id, ip_address)
    except Exception as e:
        logger.exception(e)
        await message.answer(locale.get("error-msg"))
    await manager.done()


async def start_changing_authorization_type(
    call: types.CallbackQuery | types.Message,
    widget: Any,
    manager: DialogManager,
    allowed_ip_id: int = None,
):

    locale: Locale = manager.middleware_data.get("locale")
    scheduler: AsyncIOScheduler = manager.middleware_data.get("scheduler")
    bot: Bot = manager.middleware_data.get("bot")
    config: Settings = manager.middleware_data.get("config")
    order_id: int = manager.start_data.get("order_id")
    session_factory = manager.middleware_data.get("session_factory")
    authorization_type: str = manager.dialog_data.get(
        "authorization_type", "by_password"
    )
    user_id = call.from_user.id

    try:
        scheduler.add_job(
            jobs.change_authorization_type_job,
            args=(
                bot,
                locale,
                session_factory,
                user_id,
                order_id,
                allowed_ip_id,
                authorization_type,
                config,
            ),
        )

        logger.info(f"Добавлена задача по смене авторизации заказа {order_id}")

        if isinstance(call, types.CallbackQuery):
            await call.message.answer(locale.get("in-work-msg"))
        else:
            await call.answer(locale.get("in-work-msg"))
    except Exception as e:
        logger.exception(e)
        if isinstance(call, types.CallbackQuery):
            await call.message.answer(locale.get("error-msg"))
        else:
            await call.answer(locale.get("error-msg"))
    await manager.done()


authorization_types_window = Window(
    LocaleText("select-authorization-type"),
    Group(
        Button(
            LocaleText("by-ip-address"),
            id="by_ip_address",
            on_click=select_ip_address,
        ),
        Button(
            LocaleText("by-password"),
            id="by_password",
            on_click=start_changing_authorization_type,
            when=F["proxy_is_mobile_private"],
        ),
        width=2,
    ),
    Cancel(LocaleText("back-btn")),
    getter=server_type_getter,
    state=ChangeAuthorizationSG.select_authorization_type,
)

select_ip_address_window = Window(
    LocaleText("select-ip-address"),
    ScrollingGroup(
        Select(
            Format("{item.ip_address}"),
            "catselsel",
            lambda allowed_ip: allowed_ip.id,
            "allowed_ips",
            on_click=start_changing_authorization_type,
        ),
        width=2,
        height=4,
        id="catsel",
    ),
    Start(
        LocaleText("add-ip-address"),
        id="create_ip_address",
        state=CreateIPSG.create_ip_address,
    ),
    Back(LocaleText("back-btn")),
    Cancel(LocaleText("cancel-btn")),
    getter=user_ips_getter,
    state=ChangeAuthorizationSG.select_ip_address,
)


authorization_types_dialog = Dialog(
    authorization_types_window, select_ip_address_window
)


create_ip_window = Window(
    LocaleText("enter-ip-address"),
    TextInput("ipaddressinp", str, on_success=add_ip_address),
    Cancel(LocaleText("back-btn")),
    state=CreateIPSG.create_ip_address,
)

create_ip_dialog = Dialog(create_ip_window)


async def start_authorization_change(
    message: types.Message, widget: Any, manager: DialogManager
):
    if manager.start_data:
        order_id: int = manager.start_data.get("order_id")
    else:
        order_id: int = manager.dialog_data.get("order_id")

    await manager.start(
        ChangeAuthorizationSG.select_authorization_type, {"order_id": order_id}
    )
